<template>
    <div>
        <Search @search="onSearch" @reset="onReset" />
        <TreeTableHeder :isParentDisabled="isParentDisabled" @add="addHandle" />
        <TreeTable
            ref="TreeTableRef"
            v-loading="state.loading"
            :props="treeProps"
            node-key="id"
            lazy
            :load="loadNode"
            @node-expand="nodeExpandHandle"
            @delete="deleteHandle"
            @edit="editHandle"
            @add="addChildHandle" />
        <Pagination
            :total="state.totalCount"
            :page-size="searchParams.perPage"
            :current-page="searchParams.page"
            @size-change="onSizeChange"
            @pageChange="onPageChange" />
        <AddDia ref="AddDiaRef" @success="successHandel" />
    </div>
</template>

<script setup>
import Search from './search.vue';
import TreeTableHeder from './treeTableHeder.vue';
import TreeTable from './treeTable.vue';
import Pagination from '@/components/Pagination.vue';
import AddDia from './addDia.vue';

import request from '@/request';
import { getGoodsClassListHook, getGoodsClassChildListHook } from '@/hooks/goods';

import { ElMessage } from 'element-plus';
import { computed, reactive, ref } from 'vue';

const TreeTableRef = ref(null);
const state = reactive({
    defaultExpandedKeys: [],
    totalCount: 0,
    level: 0,
    loading: false
});
// 一级类目最大新增数量 100
const isParentDisabled = computed(() => {
    return state.totalCount >= 100;
});
const searchParams = reactive({
    name: '',
    page: 1,
    perPage: 10
});
const treeProps = {
    label: 'name',
    children: 'children',
    isLeaf: 'hasChildren' // 是否有子节点
};
const childRequestSuccess = {};
let nodeHad = null;
let resolveHad = null;
let currentData = {};

/* ------------------------------------------------ 获取列表数据 start ------------------------------------------------ */
const loadNode = async (node = nodeHad, resolve = resolveHad) => {
    if (node.level === 0) {
        state.loading = true;
        nodeHad = node;
        resolveHad = resolve;
        const data = await getGoodsClassListHook(searchParams);
        state.loading = false;
        state.totalCount = data.totalCount;
        node.childNodes = [];
        resolve(data.list);
        return;
    }
    const id = node.data.id;
    const childList = await getGoodsClassChildListHook(id);
    childRequestSuccess[id] = childList[0].id;
    resolve(childList);
};
const onSearch = v => {
    Object.assign(searchParams, v);
    loadNode();
};
const onReset = v => {
    Object.assign(searchParams, v);
    loadNode();
};

const onSizeChange = v => {
    searchParams.page = 1;
    searchParams.perPage = v;
    loadNode();
};
const onPageChange = v => {
    searchParams.page = v;
    loadNode();
};
const nodeExpandHandle = (data, node) => {
    if (childRequestSuccess[data.id]) return;
    node.loaded = false;
    node.expand(); // 主动调用展开节点方法，重新查询该节点下的所有子节点
};
/* ------------------------------------------------ 获取列表数据 end ------------------------------------------------ */

const successHandel = async () => {
    state.type === 'add' ? addSuccess() : editSuccess();
};
const AddDiaRef = ref(null);
/* ------------------------------------------------ 新增 start ------------------------------------------------ */
const addHandle = () => {
    state.type = 'add';
    state.level = 0;
    AddDiaRef.value.openDialog({ type: 'add', child: false, id: 0 });
};
const addChildHandle = ({ node, data }) => {
    state.type = 'add';
    state.level = node.level;
    currentData = data;
    let parentName = '';
    if (node.level === 1) {
        parentName = data.name;
    }
    if (node.level === 2) {
        const oneName = node.parent.data.name;
        parentName = oneName + '/' + data.name;
    }
    AddDiaRef.value.openDialog({ type: 'add', child: true, parentName, id: data.id });
};
const addSuccess = async () => {
    if (state.level === 0) {
        loadNode();
    }
    if (state.level === 1) {
        if (currentData.hasChildren) {
            loadNode();
        } else {
            const id = currentData.id;
            const list = await getGoodsClassChildListHook(id);
            TreeTableRef.value.$refs.treeRef.updateKeyChildren(currentData.id, list);
        }
    }
    if (state.level === 2) {
        const typeId = currentData.hasChildren ? currentData.pid : currentData.id;
        const list = await getGoodsClassChildListHook(typeId);
        TreeTableRef.value.$refs.treeRef.updateKeyChildren(typeId, list);
    }
};
/* ------------------------------------------------ 新增 end ------------------------------------------------ */

/* ------------------------------------------------ 编辑 start ------------------------------------------------ */
const editHandle = ({ node, data }) => {
    state.type = 'edit';
    state.level = node.level;
    currentData = data;
    let parentName;
    if (node.level === 2) {
        parentName = node.parent.data.name;
    }
    if (node.level === 3) {
        const twoName = node.parent.data.name;
        const oneName = node.parent.parent.data.name;
        parentName = oneName + ' / ' + twoName;
    }
    AddDiaRef.value.openDialog({ type: 'edit', parentName, child: !!data.pid, id: data.id, name: data.name });
};
const editSuccess = async () => {
    if (state.level === 1) {
        loadNode();
    }
    if ([2, 3].includes(state.level)) {
        const typeId = currentData.pid;
        const list = await getGoodsClassChildListHook(typeId);
        TreeTableRef.value.$refs.treeRef.updateKeyChildren(typeId, list);
    }
};
/* ------------------------------------------------ 编辑 end ------------------------------------------------ */

/* ------------------------------------------------ 删除 start ------------------------------------------------ */
const deleteHandle = async ({ node, data }) => {
    await request('delGoodsClass', { id: data.id });
    ElMessage.success('删除成功');
    if (node.level === 1) {
        if (searchParams.page > 1 && state.totalCount % searchParams.perPage === 1) searchParams.page--;
        loadNode();
        return;
    }
    TreeTableRef.value.$refs.treeRef.remove(node);
};
</script>
